package server;
import java.net.*; 
import java.io.*; 

import common.HitInformation;
import common.Matches;
import common.Shared;


public class FTP_Handler extends Thread
{    
	private Socket control    = null,
   			  	   clientData = null;
   
	private DataInputStream  in [] = new DataInputStream [ 2 ];
	private DataOutputStream out[] = new DataOutputStream[ 2 ];
    
	/** F T P _ H a n d l e r (   )
	 * ------------------------------------------------------------------------
	 *   Initializes the input and output streams for the socket. 
	 */
	public FTP_Handler
			( Socket control )
	{
		this.control = control;
		   
		try {
			in [ Shared.CONTROL_LINE ] =
					new DataInputStream( control.getInputStream() );
		} catch( IOException e )
		{
			Shared.error( "Could not create input control line from client." );
			System.exit( 1 );
		}

		try {
			out[ Shared.CONTROL_LINE ] =
					new DataOutputStream ( control.getOutputStream() );
		} catch( IOException e ) 
		{
			Shared.error( "Could not create output control line to client." );
			System.exit( 1 );
		}
	}
	   
	/** r u n (   )
	 * ------------------------------------------------------------------------
	 *   Method that gets called when the thread is started. This method loops,
	 *   waiting for commands from the client.
	 */
	public void run( )
	{ 
		System.out.println
				( " -- Connected to client \"" +
				  control.getInetAddress() +
				  "\" on port " +
				  control.getLocalPort() + 
				  "." );
		
		String line = "";
		
		while( true )
		{
			try {
				line = in[ Shared.CONTROL_LINE ].readUTF();
			} catch( IOException e ) {
				Shared.error( "Client has unexpectedly terminated!" );
				break;
			}
			
			if( line == null )
				break;
			
			System.out.println
					( "From client (" +
					  control.getLocalPort() +
					  "): \"" + 
					  line + 
					  "\"" );
			
			String parsed[] = line.split( " " );
			parsed[ 0 ] = parsed[ 0 ].toUpperCase();

			if( parsed[ Shared.COMMAND ].equals( Shared.QUIT ) )
			{
				System.out.println
						( " -- Client \"" +
					 	  control.getInetAddress() + 
						  "\" is disconnecting from port " +
						  control.getLocalPort() + 
						  "." );
				
				Shared.closeObject( control );
				Shared.closeObject( in [ Shared.CONTROL_LINE ] );
				Shared.closeObject( out[ Shared.CONTROL_LINE ] );
				
				break;
			}
			else if( parsed[ Shared.COMMAND ].equals( Shared.QUERY ) )
			{
				String[] list = new File( Shared.HOSTED ).
						 list ( new Matches( parsed[ Shared.FILENAME ] ) );
				long[] sizes = new long[list.length];
				for(int x = 0; x < list.length; x++ ){
					sizes[x] = new File( Shared.HOSTED + list[x]).length();
				}
				HitInformation hit = new HitInformation(list,sizes,control.getLocalAddress(),control.getLocalPort());
				
				try {
					Shared.sendHit( hit, out[ Shared.CONTROL_LINE ] );
				} catch( Exception e ) {}

			}
			else if( parsed[ Shared.COMMAND ].equals( Shared.ROBOT ) )
			{
				String[] list = new File( Shared.HOSTED ).
						 list ( new Matches( parsed[ Shared.FILENAME ] ) );
				long[] sizes = new long[list.length];
				for(int x = 0; x < list.length; x++ ){
					sizes[x] = new File( Shared.HOSTED + list[x]).length();
				}
				HitInformation hit = new HitInformation(list,sizes,control.getLocalAddress(),control.getLocalPort());
				
				try {
					Shared.sendHit( hit, out[ Shared.CONTROL_LINE ] );
				} catch( Exception e ) {}
				
			}
			else if( parsed[ Shared.COMMAND ].equals( Shared.RETRIEVE ) )
			{
				try {
					System.out.print
							( " -- Trying to connect to client..." );
					
					clientData = 
						new Socket
							( control.getInetAddress(), 
							  in[ Shared.CONTROL_LINE ].readInt() );
					
					System.out.println
							( "connected." );
				} catch( IOException e ) {
					Shared.error
							( "Could not create data connection with server!" );
					continue;
				}

				try {
					System.out.println
							( " -- Sending file to client." );
					Shared.storeFile
							( Shared.HOSTED + parsed[ Shared.FILENAME ],
							  out[ Shared.DATA_LINE ] =
								  	new DataOutputStream
								  			( clientData.getOutputStream() ) );
				} catch( IOException e ) {
					Shared.error
							( "Could not get the data stream from the data" +
							  "connection!" );
				}
				
				Shared.closeObject( clientData );
			}
		}
	}
}
